package com.shangxia.common.util;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zhouya38158
 * @date 2021/11/10 9:14
 */
@Slf4j
public class TreeUtil<T> {
    /**
     * 列表
     */
    @NonNull
    private List<T> list;

    /**
     * 存在根节点
     */
    private T root;

    /**
     * 父关系 字段 类似于 id 与 parentId 的 parentId
     */
    @NonNull
    private String parentField;

    /**
     * 子关系 字段 类似于 id 与 parentId 的id
     */
    @NonNull
    private String sonField;

    /**
     * 子列表
     */
    @NonNull
    private String children;


    /**
     * @param list 转换树的源集合
     * @param parentField 父关系 字段
     * @param sonField 子关系 字段
     * @param children
     * @param comparator  排序比较器
     */
    public TreeUtil(@NonNull List<T> list, @NonNull String parentField, @NonNull String sonField, @NonNull String children, Comparator comparator) {
        this.list = list;
        this.parentField = parentField;
        this.sonField = sonField;
        this.children = children;
        this.comparator = comparator;
    }

    /**
     * 排序比较器
     */
    private Comparator comparator;

    public TreeUtil(@NonNull List<T> list, T root, @NonNull String parentField, @NonNull String sonField, @NonNull String children) {
        this.list = list;
        this.root = root;
        this.parentField = parentField;
        this.sonField = sonField;
        this.children = children;
    }

    public TreeUtil(@NonNull List<T> list, @NonNull String parentField, @NonNull String sonField, @NonNull String children) {
        this.list = list;
        this.parentField = parentField;
        this.sonField = sonField;
        this.children = children;
    }


    public T fillRootTree() {
        T root = ObjectUtils.isEmpty(this.root) ? getRootByParentFieldIsNull() : this.root;
        return fillChild(root);
    }

    public T fillTree() {
        T root = getRootByParentFieldIsNull();
        return fillChild(root);
    }

    /**
     * 根节点的父节点为空
     *
     * @return 根节点
     */
    private T getRootByParentFieldIsNull() {
        List<T> collect = list.stream().filter(tree -> {
            final BeanWrapper bean = new BeanWrapperImpl(tree);
            return !StringUtils.hasLength((String) bean.getPropertyValue(parentField));
        }).collect(Collectors.toList());
        return CollectionUtils.isEmpty(collect) ? null : collect.get(0);
    }

    private T fillChild(@NonNull T root) {
        final BeanWrapper rootBean = new BeanWrapperImpl(root);
        List<T> collect = list.stream().filter(tree -> {
            BeanWrapper bean = new BeanWrapperImpl(tree);
            return Objects.equals(rootBean.getPropertyValue(sonField), bean.getPropertyValue(parentField));
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(collect)) {
            try {
                if (!ObjectUtils.isEmpty(comparator)) {
                    collect.sort(comparator);
                } else if (root instanceof Comparator) {
                    collect = collect.stream().sorted().collect(Collectors.toList());
                }
            } catch (Exception e) {
                log.error("{}排序异常", root.getClass().getName(), e);
            }
            // e->fillChild(e) ==> this::fillChild
            collect.forEach(this::fillChild);
        }
        rootBean.setPropertyValue(children, collect);
        return root;
    }
}
